package one.stand.controller;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import com.github.pagehelper.PageHelper;
import com.jmp.autocofiguration.util.OssUtil2;
import com.jmp.service.api.admin.TicketApi;
import com.jmp.service.api.admin.dto.*;
import lombok.extern.slf4j.Slf4j;
import one.stand.advice.ResultEnum;
import one.stand.common.cache.AdminServiceBaseCacheModel;
import one.stand.dto.ConvertUtils;
import one.stand.dto.PageResponse2;
import one.stand.mapper.TicketAccountMapperExt;
import one.stand.mapper.TicketOrderMapperExt;
import one.stand.mapper.TicketTimeMapperExt;
import one.stand.model.*;
import one.stand.service.TicketService;
import one.stand.util.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.io.InputStream;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.UUID;

/**
 * @author cjr
 */
@RestController
@Slf4j
public class TicketController implements TicketApi {

    @Autowired
    private TicketService ticketService;
    @Autowired
    private TicketAccountMapperExt ticketAccountMapperExt;
    @Autowired
    private TicketTimeMapperExt ticketTimeMapperExt;
    @Autowired
    private TicketOrderMapperExt ticketOrderMapperExt;

    @Autowired
    private RedisUtil redisUtil;

    @Override
    public ResultModel<TicketInfoResponse> info(@RequestBody TicketInfoRequest request) {
        TicketQrCacheModel ticketQrCacheModel = new TicketQrCacheModel(redisUtil, request.getQrCode());
        Integer id = ticketQrCacheModel.get();
        AssertUtil.nonNull(id, ResultEnum.PARAM_CHECK, "二维码已失效");

        TicketAccount ticketAccount = ticketAccountMapperExt.selectByPrimaryKey(id);
        AssertUtil.nonNull(ticketAccount, ResultEnum.PARAM_CHECK, "奖券不存在");

        TicketInfoResponse response = TicketInfoResponse.builder()
                .userId(ticketAccount.getUserId())
                .orderMoney(ticketAccount.getMoney())
                .orderNum(ticketAccount.getOrderNum())
                .num(ticketAccount.getNum())
                .status(ticketAccount.getStatus())
                .checkTime(ticketAccount.getCheckTime())
                .checkUser(ticketAccount.getCheckUser())
                .build();
        return ResultModel.success(response);
    }

    @Override
    public ResultModel<TicketInfoQrResponse> infoQr(@RequestBody TicketInfoQrRequest request) {

        QrCacheModel qrCacheModel = new QrCacheModel(redisUtil, request.getUserId());
        TicketInfoQrResponse vo = qrCacheModel.get();
        if (Objects.nonNull(vo)) return ResultModel.success(vo);

        TicketTime ticketTime = ticketService.getTicketTime();
        TicketInfoQrResponse.TicketInfoQrResponseBuilder response = TicketInfoQrResponse.builder()
                .startTime(ticketTime.getStime())
                .endTime(ticketTime.getEtime())
                .qrCode("https://qj-c.oss-cn-shanghai.aliyuncs.com/config/qr_default.jpg")
                .qrTimes(TicketQrCacheModel.TIME);

        TicketAccount ticketAccount = ticketAccountMapperExt.select(ticketTime.getId(), request.getUserId());
        if (Objects.isNull(ticketAccount)) {
            ticketAccount = new TicketAccount();
            ticketAccount.setType(ticketTime.getId());
            ticketAccount.setUserId(request.getUserId());
            ticketAccount.setStatus(0);
            ticketAccountMapperExt.insertSelective(ticketAccount);
            ticketAccount = ticketAccountMapperExt.select(ticketTime.getId(), request.getUserId());
        }
        response.orderMoney(ticketAccount.getMoney())
                .orderNum(ticketAccount.getOrderNum())
                .num(ticketAccount.getNum())
                .status(ticketAccount.getStatus());

        Date date = new Date();
        if (ticketTime.getEtime().after(date) && ticketAccount.getStatus() == 0) {
            String content = "tq" + String.format("%03d", ticketAccount.getType()) + ticketAccount.getUserId() + UUID.randomUUID();
            String qrCode = qrCode(content);
            TicketQrCacheModel ticketQrCacheModel = new TicketQrCacheModel(redisUtil, content);
            ticketQrCacheModel.save(ticketAccount.getId());
            response.qrCode(qrCode);
            response.qrEndTimes(DateUtil.offset(date, DateField.SECOND, TicketQrCacheModel.TIME).getTime());
        }

        vo = response.build();
        qrCacheModel.save(vo);

        return ResultModel.success(vo);
    }

    @Override
    public ResultModel use(@RequestBody TicketUseRequest request) {

        // check qr
        TicketQrCacheModel ticketQrCacheModel = new TicketQrCacheModel(redisUtil, request.getQrCode());
        Integer id = ticketQrCacheModel.get();
        AssertUtil.nonNull(id, ResultEnum.PARAM_CHECK, "二维码已失效");

        TicketAccount ticketAccount = ticketAccountMapperExt.selectByPrimaryKey(id);
        AssertUtil.nonNull(ticketAccount, ResultEnum.PARAM_CHECK, "奖券不存在");
        AssertUtil.isTrue(ticketAccount.getStatus() == 0, ResultEnum.PARAM_CHECK, "奖券已核销");

        TicketTime ticketTime = ticketTimeMapperExt.selectByPrimaryKey(ticketAccount.getType());
        AssertUtil.nonNull(ticketTime, ResultEnum.PARAM_CHECK, "活动不存在");
        Date now = new Date();
        AssertUtil.isTrue(ticketTime.getStime().before(now), "活动未开始");
        AssertUtil.isTrue(ticketTime.getEtime().after(now), "活动已过期");

        RequestContext.User user = RequestContextHolder.getRequestContext().getUser();
        ticketService.use(id, user.getUserId());

        //核销后清除缓存
        QrCacheModel qrCacheModel = new QrCacheModel(redisUtil, ticketAccount.getUserId());
        qrCacheModel.remove();

        return ResultModel.success();
    }

    @Override
    public ResultModel orderSave(@RequestBody TicketOrderSaveRequest request) {

        ticketService.orderSave(request.getId(), request.getFromCompanyId(), request.getOrderMoney(), request.getOrderNo(), request.getPhoto(), request.getPayPhoto());

        return ResultModel.success();
    }

    @Override
    public ResultModel orderPass(@RequestBody TicketOrderPassRequest request) {

        ticketService.orderPass(request.getId());

        return ResultModel.success();
    }

    @Override
    public ResultModel orderRefuse(@RequestBody TicketOrderPassRequest request) {

        ticketService.orderRefuse(request.getId(), request.getMemo());

        return ResultModel.success();
    }

    @Override
    public ResultModel orderMemo(@RequestBody TicketOrderMemoDto request) {
        ticketService.orderMemo(request.getId(), request.getMemoTel());
        return ResultModel.success();
    }

    @Override
    public ResultModel<TicketOrderCountVo> orderCount(@RequestBody TicketOrderCountDto request) {
        TicketOrderCountVo vo = ticketOrderMapperExt.selectOrderCount(request.getUserId());
        return ResultModel.success(vo);
    }

    @Override
    public ResultModel<TicketOrderListVo> orderList(@RequestBody TicketOrderListDto request) {

        PageHelper.startPage(request.getPageNum(), request.getPageSize());
        List<TicketOrder> orderList = ticketOrderMapperExt.selectOrderList(request.getUserId());
        PageResponse2<TicketOrderListVo.Order> orderPage = ConvertUtils.page2(orderList, order -> {
            return TicketOrderListVo.Order.builder()
                    .id(order.getId())
                    .fromCompanyId(order.getFromCompanyId())
                    .orderNo(order.getOrderNo())
                    .orderMoney(order.getOrderMoeny())
                    .ctime(order.getCtime().getTime())
                    .status(order.getStatus())
                    .memo(order.getMemo())
                    .build();
        });

        TicketOrderListVo vo = TicketOrderListVo.builder()
                .page(orderPage)
                .build();
        return ResultModel.success(vo);
    }

    @Override
    public ResultModel<TicketOrderInfoVo> orderInfo(@RequestBody TicketOrderInfoDto request) {
        TicketOrder ticketOrder = ticketOrderMapperExt.selectByPrimaryKey(request.getOrderId());
        AssertUtil.nonNull(ticketOrder, ResultEnum.PARAM_CHECK, "订单不存在");

        final RequestContext.User optUser = RequestContextHolder.getRequestContext().getUser();
        AssertUtil.isTrue(ticketOrder.getCreater().equals(optUser.getUserId()), ResultEnum.PARAM_CHECK, "无权限");

        TicketOrderInfoVo vo = TicketOrderInfoVo.builder()
                .id(ticketOrder.getId())
                .fromCompanyId(ticketOrder.getFromCompanyId())
                .orderNo(ticketOrder.getOrderNo())
                .orderMoney(ticketOrder.getOrderMoeny())
                .photo(ticketOrder.getPhoto())
                .payPhoto(ticketOrder.getPayPhoto())
                .status(ticketOrder.getStatus())
                .build();
        return ResultModel.success(vo);
    }

    private String qrCode(String content) {
        InputStream inputStream = null;
        try {
            inputStream = QRCodeUtil.encodeInputStream(content);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return OssUtil2.upload(inputStream, OssUtil2.FileSuffix.jpg);
    }

    private static class QrCacheModel extends AdminServiceBaseCacheModel<TicketInfoQrResponse> {

        public QrCacheModel(RedisUtil redisUtil, Integer userId) {
            super(redisUtil, "qr@" + userId, 20 * 60);
        }
    }
}
